/*!
 * \file nghttp2_header.c
 *
 * \brief http/2.0 头部解析 函数
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 *
 * \version 3.0
 * \author geyh
 * \date 2016/01/28
 *
 */
#include <stdint.h>
#include <stddef.h>
#include "nghttp2_header.h"
#include "../comm/http_comm.h"

/*! http/2 Huffman 头解压缩
 *
 * \p_in        (uint8_t *      入力数据)
 * \inlen       (size_t         数据长度)
 * \p_st_private    (L7session_http_private *      私有数据)
 * \p_st_body_data         (Frreport_body_data *       上报链表)
 * \final                   int
 * \i_flag_need         (是否需要数据)
 *
 * \return                  成功：0\n
 *                          失败：其他\n
 */
int inflate_header_block(uint8_t *p_in, size_t inlen, L7session_http_private *p_st_private, Frreport_body_data *p_st_body_data, int final, int i_flag_need)
{
    ssize_t rv;
    int inflate_flags = 0;
    nghttp2_nv nv;
    nghttp2_hd_inflater *p_inflater_ptr = NULL;
    int i_ret = 0;

    if(p_in == NULL || p_st_private == NULL || p_st_private->p_http2_sess == NULL)
        return -1;

    memset(&nv, 0x00, sizeof(nghttp2_nv));

    if(i_flag_need && p_st_body_data == NULL)
        return -1;

    if(p_st_private->p_inflater_ptr == NULL)
    {
        i_ret = nghttp2_hd_inflate_new(&p_st_private->p_inflater_ptr);
        if(i_ret != 0)
            return -1;
    }
    p_inflater_ptr = p_st_private->p_inflater_ptr;

    while(inlen)
    {
        rv = nghttp2_hd_inflate_hd(p_inflater_ptr, &nv, &inflate_flags, p_in, inlen, final);

        if(rv < 0)
        {
            nghttp2_hd_inflate_del(p_st_private->p_inflater_ptr);
            p_st_private->p_inflater_ptr = NULL;
            return -1;
        }
//                printf("%s:%s\n", nv.name, nv.value);

        if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT)
            http_header_analysis((char *)nv.name, (char *)nv.value, p_st_private, p_st_body_data, i_flag_need, p_st_private->i_frame_type);

        if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL)
        {
            nghttp2_hd_inflate_end_headers(p_inflater_ptr);
            break;
        }

        if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0)
            break;

        //todo
        p_in += rv;
        inlen -= rv;

    }

    return 0;
}

/*! http/2 头信息解析
 *
 * \p_data        (char *      入力数据)
 * \ul_data_len      (unsigned long         数据长度)
 * \p_st_private    (L7session_http_private *      私有数据)
 * \p_st_body_data         (Frreport_body_data *       上报链表)
 * \i_flag_need         (是否需要数据)
 *
 * \return                  成功：FR_SUCC\n
 *                          失败：FR_FAIL\n
 */
int http_header_inflate(char *p_data, unsigned long ul_data_len, L7session_http_private *p_st_private, Frreport_body_data *p_st_body_data, int i_flag_need)
{
    int i_ret = 0;

    if(p_data == NULL || ul_data_len == 0 || p_st_private == NULL)
        return FR_FAIL;

    if(i_flag_need && p_st_body_data == NULL)
        return FR_FAIL;

    i_ret = inflate_header_block((uint8_t*)p_data, ul_data_len, p_st_private, p_st_body_data, 1, i_flag_need);

    return i_ret == 0 ? FR_SUCC : FR_FAIL;

}

